package com.jsptpd.smartauth.modules.business.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.jsptpd.smartauth.common.util.DateUtil;
import com.jsptpd.smartauth.common.util.StringUtil;
import com.jsptpd.smartauth.common.util.WeChatUtil;
import com.jsptpd.smartauth.modules.business.dao.db1.BindInfoMapper;
import com.jsptpd.smartauth.modules.business.model.BindInfo;
import com.jsptpd.smartauth.modules.business.model.Error;
import com.jsptpd.smartauth.modules.business.model.RespObj;
import com.jsptpd.smartauth.modules.business.model.WeChatToken;
import com.jsptpd.smartauth.modules.business.service.IBindService;
import com.jsptpd.smartauth.modules.business.utils.Constants;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Service
public class BindServiceImpl extends ServiceImpl<BindInfoMapper, BindInfo> implements IBindService {

    @Value("${config.bind.succ}")
    private String cfgBindSucc;
    @Value("${config.bind.errUpdate}")
    private String cfgBindErrUpdate;
    @Value("${config.bind.errState}")
    private String cfgBindErrState;
    @Value("${config.bind.errToken}")
    private String cfgBindErrToken;
    @Value("${config.bind.errQRcode}")
    private String cfgBindErrQRcode;
    @Value("${config.bind.errExp}")
    private String cfgBindErrExp;
    @Value("${config.bind.errEnd}")
    private String cfgBindErrEnd;
    @Value("${config.bind.errDupl}")
    private String cfgBindErrDupl;

    @Value("${config.bind.propNeedCheck}")
    private boolean propNeedCheck;

    @Autowired
    RestTemplate restTemplate;

    @Value("${config.bind.orderTime}")
    int orderTime;

    private WeChatUtil weChatUtil = new WeChatUtil();

    @Override
    public RespObj bindWechat(String code, String state,String appId,int order) throws IOException {
        Error error = new Error();
        RespObj<String> respData = new RespObj<String>(error,"");

        if(appId==null || appId.isEmpty()){
            respData.getError().setErrCode(Constants.WX_BIND_ERRCODE_STATE);
            respData.getError().setErrMessage(StringUtil.getValue(cfgBindErrState,Constants.WX_BIND_ERRMSG_STATE));
            return respData;
        }

        if (code != null) {
            //根据code获取token
            WeChatToken weChatToken = weChatUtil.getWxTokenByCode(code,appId);
            if (weChatToken!=null
                    && StringUtil.isEmpty(weChatToken.getErrCode())
                    && StringUtil.isNotEmpty(weChatToken.getAccessToken())
                    && StringUtil.isNotEmpty(weChatToken.getOpenId())
                    && StringUtil.isNotEmpty(weChatToken.getUnionId())) {
                //获取nickName
                String nickName = weChatUtil.getNickNameByToken(weChatToken.getAccessToken(),weChatToken.getOpenId());
                //完成绑定
                if (state != null) {
                    BindInfo bi = new BindInfo();
                    if(order == Constants.WX_BIND_MODE_UNORDER) {
                        //未预约：这个微信或账号是否已经绑定
                        List<BindInfo> results = selectList(new EntityWrapper<BindInfo>()
                                .where("UNION_ID={0}", weChatToken.getUnionId())
                                .or("USER_ID={0}", state));
                        if (results.size() > 0) {
                            respData.getError().setErrCode(Constants.WX_BIND_ERRCODE_DUPL);
                            respData.getError().setErrMessage(StringUtil.getValue(cfgBindErrDupl, Constants.WX_BIND_ERRMSG_DUPL));
                        } else {//写入新的绑定
                            bi.setUserId(state);
                            bi.setOpenId(weChatToken.getOpenId());
                            bi.setUnionId(weChatToken.getUnionId());
                            bi.setNickName(nickName);
                            bi.setStatus(Constants.WX_BIND_STATUS_DONE);
                            bi.setCreateTime(new Date());
                            bi.setEmployeeType(1);
                            bi.setEndTime(new Date());
                            bi.setPropId("");
                            bi.setUseCount(0);
                            boolean isSuccess = insert(bi);
                            if (isSuccess) {
                                respData.getError().setErrCode(Constants.WX_BIND_ERRCODE_SUCC);
                                respData.getError().setErrMessage(StringUtil.getValue(cfgBindSucc, Constants.WX_BIND_ERRMSG_SUCC));
                            } else {
                                respData.getError().setErrCode(Constants.WX_BIND_ERRCODE_UPDATE);
                                respData.getError().setErrMessage(StringUtil.getValue(cfgBindErrUpdate, Constants.WX_BIND_ERRMSG_UPDATE));
                            }
                        }
                    }else if(order == Constants.WX_BIND_MODE_ORDER){
                        //预约：该记录是否有效
                        List<BindInfo> results = selectList(new EntityWrapper<BindInfo>().eq("USER_ID",state));
                        if(results==null ||results.size()<=0){
                            respData.getError().setErrCode(Constants.WX_BIND_ERRCODE_END);
                            respData.getError().setErrMessage(StringUtil.getValue(cfgBindErrEnd,Constants.WX_BIND_ERRMSG_END));
                        }else{
                            bi = results.get(0);
                            if(bi.getStatus() == Constants.WX_BIND_STATUS_WAIT
                                    && bi.getUseCount()>0
                                    && new Date().getTime()<bi.getEndTime().getTime() ){
                                bi.setOpenId(weChatToken.getOpenId());
                                bi.setUnionId(weChatToken.getUnionId());
                                bi.setNickName(nickName);
                                bi.setStatus(Constants.WX_BIND_STATUS_DONE);
                                bi.setUseCount(bi.getUseCount()-1);
                                boolean isSuccess = update(bi,new EntityWrapper<BindInfo>().eq("USER_ID",state));
                                if(isSuccess){
                                    respData.getError().setErrCode(Constants.WX_BIND_ERRCODE_SUCC);
                                    respData.getError().setErrMessage(StringUtil.getValue(cfgBindSucc, Constants.WX_BIND_ERRMSG_SUCC));
                                }else{
                                    respData.getError().setErrCode(Constants.WX_BIND_ERRCODE_END);
                                    respData.getError().setErrMessage(StringUtil.getValue(cfgBindErrEnd,Constants.WX_BIND_ERRMSG_END));
                                }
                            }else{
                                respData.getError().setErrCode(Constants.WX_BIND_ERRCODE_END);
                                respData.getError().setErrMessage(StringUtil.getValue(cfgBindErrEnd,Constants.WX_BIND_ERRMSG_END));
                            }
                        }
                    }
                } else {
                    respData.getError().setErrCode(Constants.WX_BIND_ERRCODE_STATE);
                    respData.getError().setErrMessage(StringUtil.getValue(cfgBindErrState,Constants.WX_BIND_ERRMSG_STATE));
                }
            } else {
                respData.getError().setErrCode(Constants.WX_BIND_ERRCODE_TOKEN);
                respData.getError().setErrMessage(String.format(StringUtil.getValue(cfgBindErrToken,Constants.WX_BIND_ERRMSG_TOKEN),weChatToken.getErrCode()));
            }
        } else {
            respData.getError().setErrCode(Constants.WX_BIND_ERRCODE_QRCODE);
            respData.getError().setErrMessage(StringUtil.getValue(cfgBindErrQRcode,Constants.WX_BIND_ERRMSG_QRCODE));
        }

        return respData;
    }

    @Override
    public RespObj bindOrder(String userId, int employeeType,String queryPropUrl) {
        Error error;
        BindInfo bindInfo = new BindInfo();
        bindInfo.setUseCount(1);
        bindInfo.setEndTime(DateUtil.getNewDate(new Date(),orderTime, Calendar.HOUR));
        bindInfo.setStatus(Constants.WX_BIND_STATUS_WAIT);
        bindInfo.setCreateTime(new Date());

        if(userId != null) {
            if(employeeType == Constants.EMPLOYEE_TYPE_WX){
                String url = String.format(StringUtil.getValue(queryPropUrl, Constants.URL_QUERY_PROP), userId);
                String result;
                if(propNeedCheck) {
                    try {
                        result = restTemplate.getForObject(url, String.class);
                    } catch (Exception e) {
                        result = null;
                    }
                }else{
                    result = "true";
                }

                if(result!=null && "true".equals(result)){//有权限生成二维码
                    //生成随机序列作为邀请的用户名
                    bindInfo.setUserId(StringUtil.shortUUID());
                    bindInfo.setPropId(userId);
                    bindInfo.setEmployeeType(Constants.EMPLOYEE_TYPE_WX);
                }else{ //无推荐人生成二维码权限
                    error = new Error(Constants.PROPQR_ERRCODE_AUTH,Constants.PROPQR_ERRMSG_AUTH);
                    return new RespObj<String>(error, "");
                }
            } else if(employeeType == Constants.EMPLOYEE_TYPE_EM) {
                bindInfo.setUserId(userId);
                bindInfo.setPropId("");
                bindInfo.setEmployeeType(Constants.EMPLOYEE_TYPE_EM);
            } else {
                error = new Error(Constants.COMMON_ERRCODE_FAIL, Constants.COMMON_ERRMSG_FAIL);
                return new RespObj<String>(error, "");
            }

            List<BindInfo> results = selectList(new EntityWrapper<BindInfo>()
                    .where("USER_ID={0}", bindInfo.getUserId())
                    .andNew("UNION_ID!={0}", ""));
            if (results != null && results.size() > 0) {
                error = new Error(Constants.COMMON_ERRCODE_FAIL, Constants.COMMON_ERRMSG_FAIL);
                return new RespObj<String>(error, "");
            }

            if (insertOrUpdate(bindInfo)) {
                error = new Error(Constants.COMMON_ERRCODE_SUCC, Constants.COMMON_ERRMSG_SUCC);
                return new RespObj<String>(error, bindInfo.getUserId());
            } else {
                error = new Error(Constants.COMMON_ERRCODE_FAIL, Constants.COMMON_ERRMSG_FAIL);
                return new RespObj<String>(error, "");
            }
        } else {
            error = new Error(Constants.COMMON_ERRCODE_FAIL, Constants.COMMON_ERRMSG_FAIL);
            return new RespObj<String>(error, "");
        }
    }

    @Override
    public RespObj bindQueryUserId(String userId) {
        Error error = new Error(Constants.COMMON_ERRCODE_FAIL, Constants.COMMON_ERRMSG_FAIL);

        if(userId!=null && !userId.isEmpty()){

            List<BindInfo> results = selectList(new EntityWrapper<BindInfo>()
                    .where("USER_ID={0}", userId)
                    .andNew("STATUS={0}", Constants.WX_BIND_STATUS_DONE));
            if(results!=null && results.size()>0){
                error.setErrCode(Constants.COMMON_ERRCODE_SUCC);
                error.setErrMessage(Constants.COMMON_ERRMSG_SUCC);
            }
        }

        return new RespObj<String>(error, "");
    }
}
